package api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"prj-layout/internal/pkg/httputil"
	"prj-layout/internal/service"
	"prj-layout/model"
	"prj-layout/model/dto"
	"prj-layout/pkg/config"
	"prj-layout/pkg/ctime"
	"prj-layout/pkg/validate"
	"strconv"
	"time"
)

var UserApi = new(userApi)

type userApi struct{}

//
// Register 用户注册
// @Summary     Post 请求, 发送 multipart/form-data 类型的表单数据, 参数在消息体中
// @Description Post 请求, 发送 multipart/form-data 类型的表单数据, 参数在消息体中
// @Tags        userApi
// @Accept      mpfd
// @Produce     json
// @Param       username   formData string          false "要注册的用户名"  minlength(1) maxlength(32)
// @Param       password   formData string          false "用户密码"     minlength(1) maxlength(32)
// @Param       sex        formData int             false "0:女, 1:男" Enums(0, 1)
// @Param       tel        formData string          false "电话号码"     minlength(11) maxlength(11)
// @Param       card_front formData file            false "身份证正面图片"
// @Param       card_back  formData file            false "身份证背面图片"
// @Success     200      {object} swagger.HttpOk  "OK"
// @Failure     400      {object} swagger.Http400 "Bad Request"
// @Failure     404      {object} swagger.Http404 "Page Not Found"
// @Failure     500      {object} swagger.Http500 "InternalError"
// @Router      /user/register [post]
func (userApi) Register(c *gin.Context) {
	var registerParam dto.RegisterParam
	// 将请求数据绑定到结构体
	if err := c.ShouldBind(&registerParam); err != nil {
		trans := validate.TranslateError(err)
		zap.S().Errorf("绑定参数失败: %s\n", trans)
		httputil.InternalServerError(c, trans)
		return
	}

	insert, err := service.UserService.Register(&registerParam)
	if err != nil {
		zap.S().Errorf("注册用户失败: %s\n", err)
		httputil.InternalServerError(c, "注册用户失败")
		return
	}
	httputil.Ok(c, "注册用户成功", insert)
}

//
// Login 用户登录
// @Summary     Post 请求, 发送 multipart/form-data 类型的表单数据, 参数在消息体中
// @Description Post 请求, 发送 multipart/form-data 类型的表单数据, 参数在消息体中
// @Tags        userApi
// @Accept      mpfd
// @Produce     json
// @Param       username formData string          true "要注册的用户名" minlength(1) maxlength(32)
// @Param       password formData string          true "用户密码"    minlength(1) maxlength(32)
// @Success     200        {object} swagger.HttpOk  "OK"
// @Failure     400        {object} swagger.Http400 "Bad Request"
// @Failure     404        {object} swagger.Http404 "Page Not Found"
// @Failure     500        {object} swagger.Http500 "InternalError"
// @Router      /user/login [post]
func (userApi) Login(c *gin.Context) {
	var loginInfo dto.LoginInfo
	if err := c.ShouldBind(&loginInfo); err != nil {
		// 翻译错误消息
		translatedErr := validate.TranslateError(err)
		// 向前端回写错误数据
		httputil.InternalServerError(c, translatedErr)
		// 将错误记录到日志文件
		zap.S().Errorf("用户登录失败: %s\n", translatedErr)
		return
	}

	fmt.Printf("%#v\n", loginInfo)

	// 调用 service 层的登录函数
	token, err := service.UserService.Login(&loginInfo)
	if err != nil {
		// 向前端回写错误数据
		httputil.InternalServerError(c, err.Error())
		// 将错误记录到日志文件
		zap.S().Errorf("用户登录失败: %s\n", err.Error())
		return
	}
	httputil.Ok(c, "登录成功", token)
}

//
// GetAllUser 获取数据库中所有的用户信息
// @Summary     获取数据库中所有的用户信息
// @Description 获取数据库中所有的用户信息
// @Tags        userApi
// @Accept      json
// @Produce     json
// @Success     200 {array}  model.User      "OK"
// @Failure     400 {object} swagger.Http400 "Bad Request"
// @Failure     404 {object} swagger.Http404 "Page Not Found"
// @Failure     500 {object} swagger.Http500 "InternalError"
// @Router      /user/getAll [get]
func (userApi) GetAllUser(c *gin.Context) {
	userList, err := service.UserService.GetAll()
	if err != nil {
		httputil.InternalServerError(c, err.Error())
		zap.S().Errorf("获取全部用户信息失败: %s\n", err)
		return
	}
	httputil.Ok(c, "获取全部用户信息成功", userList)
}

//
// TestAuth 访问该接口的时候, 用户必须是已经登录成功
// @Summary     访问该接口的时候, 用户必须是已经登录成功
// @Description 访问该接口的时候, 用户必须是已经登录成功
// @Tags        UserController
// @Accept      json
// @Produce     json
// @Success     200        {object} swagger.HttpOk  "OK"
// @Failure     400        {object} swagger.Http400 "Bad Request"
// @Failure     404        {object} swagger.Http404 "Page Not Found"
// @Failure     500        {object} swagger.Http500 "InternalError"
// @Router      /user/testAuth [get]
// @Security    ApiKeyAuth
func (userApi) TestAuth(ctx *gin.Context) {
	object, exists := ctx.Get("user")
	if !exists {
		zap.L().Info("从当前上下文中获取登录用户失败")
		return
	}
	user, ok := object.(model.User)
	if !ok {
		zap.L().Info("将 interface{} 转换成 User 失败")
		return
	}
	zap.L().Info("从上下文中获取用户信息成功",
		zap.Int("id", user.ID),
		zap.String("username", user.Username),
		zap.String("password", user.Password),
		zap.Bool("sex", user.Sex),
		zap.String("tel", user.Tel),
		zap.String("card_front_path", user.CardFrontPath),
		zap.String("card_back_path", user.CardBackPath),
		zap.Time("create_time", user.CreateTime.Time),
		zap.Time("update_time", user.UpdateTime.Time),
	)
}

//
// GetPagedUserList 分页获取用户信息
// @Summary     分页获取用户信息
// @Description 分页获取用户信息
// @Tags        userApi
// @Accept      json
// @Produce     json
// @Param       pageNum  query    int             true "用户 ID"
// @Param       pageSize query    int             true "用户名称"
// @Success     200      {object} orm.Page        "OK"
// @Failure     400      {object} swagger.Http400 "Bad Request"
// @Failure     404      {object} swagger.Http404 "Page Not Found"
// @Failure     500      {object} swagger.Http500 "InternalError"
// @Router      /user/getPagedUserList [get]
func (userApi) GetPagedUserList(c *gin.Context) {
	var num = c.Query("pageNum")
	var size = c.Query("pageSize")

	pageNum, err := strconv.Atoi(num)
	if err != nil {
		httputil.InternalServerError(c, "pageNum不是数字"+err.Error())
		return
	}

	pageSize, err := strconv.Atoi(size)
	if err != nil {
		httputil.InternalServerError(c, "pageSize不是数字"+err.Error())
		return
	}

	page := service.UserService.GetPagedUserList(pageNum, pageSize)

	httputil.Ok(c, "获取数据成功", page)
}

func (userApi) TestTime(c *gin.Context) {
	// multipart/form-data
	pre := c.PostForm("pre")
	last := c.PostForm("last")

	c.JSON(http.StatusOK, gin.H{
		"pre":  pre,
		"last": last,
	})
}

func (userApi) TestTime1(c *gin.Context) {
	var u dto.TimeParam
	if err := c.ShouldBindJSON(&u); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "绑定 User 对象失败" + err.Error(),
		})
	}
	c.JSON(http.StatusOK, u)
}

func (userApi) GetUserByTime(c *gin.Context) {
	startTime, err := time.Parse(config.DateTimeLayout, "2022-08-25 00:00:00")
	if err != nil {
		fmt.Println("解析开始时间出错")
	}
	endTime, err := time.Parse(config.DateTimeLayout, "2022-08-25 23:59:59")
	if err != nil {
		fmt.Println("解析结束时间出错")
	}

	userList, err := service.UserService.GetUserByTime(ctime.CTime{Time: startTime}, ctime.CTime{Time: endTime})

	c.JSON(http.StatusOK, gin.H{
		"userList": userList,
	})
}
